﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using ecdl.demo.model.expression;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml.Packaging;

using System.Xml.Serialization;
using System.Xml;

namespace ecdl.demo.model.expression {
    public abstract class Selector : SingleExpression {

        private List<ITypeSelector> selectors = new List<ITypeSelector>();

        protected void AddSelector<In, Out>(TypedSelector<In, Out> selector) {
            selectors.Add(selector);
        }

        public override ExpressionState Evaluate(ExpressionContext context) {
            try {
                IEnumerable<object> selection = Select(context);
                return Expression.Evaluate(new ExpressionContext(selection));
            } catch (ArgumentException e) {
                return Fail(e);
            }
        }

        public IEnumerable<object> FailArgument(Type expectedType) {
            throw new ArgumentException(
                String.Format("Die %s kann nur im Kontext eines %s verwendet werden.",
                this.GetType().FullName, expectedType.FullName));
        }

        public IEnumerable<object> Select(ExpressionContext context) {
            object c = context.Context;
            foreach (var sel in selectors) {
                if (sel.InType.IsAssignableFrom(c.GetType())) {
                    return sel.DoSelect(c);
                }
            }
            return new List<object>();
        }
    }
}
